%% common_defs.hrl
%%   Definitions of common constants and data structures.
%%
%% Copyright (C) 2008, 2009 Gábor Fehér
%%
%% This file is part of ECT.
%% 
%% ECT is free software: you can redistribute it and/or modify
%% it under the terms of the GNU General Public License as published by
%% the Free Software Foundation, either version 3 of the License, or
%% (at your option) any later version.
%% 
%% ECT is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%% GNU General Public License for more details.
%% 
%% You should have received a copy of the GNU General Public License
%% along with ECT.  If not, see <http://www.gnu.org/licenses/>.
%%


% Offset of subtuples in an object tuple.
%  element(?FIELD_GLOBAL_STARTPOS, Object) is the first tuple containing fields
%  there is administrative infromation before that: currently: 
%    1. class atom
%    2. global version number
-define(FIELD_GLOBAL_STARTPOS,2).

% Offset of fields in an object subtuple.
%  element(?FIELD_LOCAL_STARTPOS, element(?FIELD_GLOBAL_STARTPOS, Object)) is the first tuple field of the object
%  there is administrative infromation before that in each subtuple: currently:
%    1. class of fields in the subtuple
%    2. local version number
-define(FIELD_LOCAL_STARTPOS,4).

%%
%% Describes a field of a class.
%%
-record(class_field,
    {
    name :: atom(),               % name of the field
    value :: any(),               % initial value of the field (defaults to undefined)
    local_pos :: integer(),       % position of the field among the local fields of the class
    global_pos :: integer(),      % position of the class containing the field, in the inheritance hierarchy
                                  %  local_pos and global_pos together specifies the position of the field
                                  %  in object instances: see classes:field_accessor/5 for example.
    access :: pulbic | private    % visibility of the field
    }).


%%
%% Describes local definition information, that is found in the module of a class.
%%  To calculate the #class{} record of a class, we need all the #class_local{} records of its superclasses, and its own 
%%  #class_local{} record.
%% Referred by the name "local class definition".
%%
-record(class_local,
   {name :: atom()                      % name of class
   ,super_class :: atom()               % name of superclass
   ,version :: integer()                % version number of class
   ,impl_module :: atom()               % name of implementation module of the class
   ,fields :: [#class_field{}]          % list of local fields, with global_pos set to undefined
   ,methods :: [{atom(), integer()}]    % name/arity pairs of local methods
   ,functions :: [{atom(), integer()}]  % name/arity pairs of exported functions
   }).


%%
%% Describes a class.
%% Referred by the name "full class definition".
%% 
-record(class,
    {name :: atom(),                 % name of class
    class_types,                     % tuple of {ClassName, ImplModule} pairs from the highest superclass to this class
    class_level :: integer(),        % the depth of this class in the inheritance chain
    fieldmap :: [#class_field{}],    % list of fields of the class
    local_version :: integer(),      % local version of the class
    global_version :: integer(),     % global version of the class
    vmt :: [{atom(), integer(), atom(), atom()}],   % method table of the class
                                     % [{MethodName, MethodArity, MethodClass, ImplementationModuleOfClass}]
    
    % derived from above attributes
    super_class :: atom(),           % Superclass of this class, can be found in class_types.
    impl_module :: atom(),           % Name of implementation module, can be derived by combining 
                                     % name and local_version.
    
    
    % local
    functions :: [{atom(), integer()}], % name/arity pairs of all the exported functions in the module of the class
    loaded_subclasses = [] :: [atom()], % List of names of loaded subclasses of this class.
                                        % If this info, is not necessary, then the list can be empty.
    src :: [#class_local{}]             % List of local definitions of all the superclasses of this class,
                                        % including this class.
    }).

%%
%% General information necessary to compile a module.
%%   And some class specific data.
%%
-record(compile_info,
    {
     local_class_data :: #class_local{},             % Local data of current class.
                                                     % Record fields have default values if the compiled module is not a class.
     class_definition :: #class{} | atom(none),      % It the compiled module defines a class, then this is its definition, otherwise none.
     fieldmap_av :: [{integer(), [#class_field{}]}], % Local fields for all the versions of the class in {Version, FieldList} pairs.
     classes :: [#class{}],     % list of all the defined classes in the compiled module
     
     proxy_module:: atom(),     % name of proxy module, if the current module is a class (only used in gen_proxy.erl)

     silent :: true | false,         % disables printing verbose messages
     cctrans :: cctrans | cctrans0,  % selects which client transformation to run
     upgrade_mode :: mode1 | mode2,  % selects object upgrade mode
     out_dir :: string()             % directory for output binary files

    }).

